from flask import Flask, request
import json, yaml, time
import os, sys
from gevent import pywsgi
import argparse

parent_path = os.path.abspath(os.path.join(__file__, *(['..'] * 4)))
sys.path.insert(0, parent_path)

from core.server.deamon.worker import update, roll_back
from core.server.modules import Keeper
from core.utils.logger_t import logging

app = Flask("EDP_deamon")


def parse_argument():
    parser = argparse.ArgumentParser()
    parser.add_argument("--config",default="configs/deamon_server_cfgs/deamon_EDP_cfg.yml",
                        help="path of server config file")
    opt = parser.parse_args()
    return opt


class Server():
    def __init__(self, cfg_file_path):
        with open(cfg_file_path,"r") as f:
            cfg = yaml.safe_load(f)
        self.server_thread_names = cfg["server_thread_names"]
        self.run_shell_paths = cfg["run_shell_paths"]
        self.keepers = {}
        for thread_name, run_shell_file_path in zip(self.server_thread_names,self.run_shell_paths):
            self.keepers[thread_name] = Keeper(thread_name,
                                run_shell_file_path,
                                cfg["keeper_stride_time"],
                                )
            self.keepers[thread_name].start()
        pass

    def update(self, save_path, backup_path):
        """
        自动化升级
        args:
            save_path: 升级包路径, 以zip结尾
            backup_path: 备份路径, 用于回滚
        """
        # 升级之前先停止keeper并且关闭其所监控的进程
        for _, keeper in self.keepers.items():
            keeper.close()
        # 开始升级程序
        logging.info("|start update, copping...|")
        update(save_path,parent_path,backup_path)
        logging.info("|coppy complete, try executing the run shell|")

        # 升级完成, 启动服务
        for run_shell_file_path in self.run_shell_paths:
            os.system('chmod +x {}'.format(run_shell_file_path))
            os.popen("sh "+ run_shell_file_path)
        logging.info("|watting 30s.....|")
        # 等待30秒后检查进程是否正常启动
        time.sleep(30)
        update_success = True
        # 遍历所有监控器
        for _, keeper in self.keepers.items():
            ret = keeper.check_running()
            if ret: # 如果能监控到进程, 则说明更新成功
                pass
            else:                      # 否则更新失败
                update_success = False
                break
        
        if update_success:  # 更新成功
            logging.info("|update SUCCESS|")
        else:               # 更新失败, 回滚
            logging.info("|update FAIL, roll back|")
            roll_back(parent_path,backup_path)
            return False
            
        # 重启服务
        for _, keeper in self.keepers.items():
            keeper.start()
        return True
        
            


@app.route("/update", methods = ["POST"])
def handle_update():
    logging.info("|call update handle|")
    response = {
    "error_no":0,
    "error_msg":"Upload file SUCCESS",
    }
    try:
        files = request.files
        update_file = files["file"]
        save_dir = "data/update"
        backup_dir_path = "data/update/backup"
        if not os.path.exists(save_dir):
            logging.info("|INFO: makedirs save_dir - {}|".format(save_dir))
            os.makedirs(save_dir)
        save_path = save_dir+"/" + update_file.filename
        update_file.save(save_path)
        ret = server.update(save_path,backup_dir_path)
        if not ret:
            raise Exception("update failed")
    except Exception as e:
        logging.error(e)
        response["error_no"] = 1
        response["error_msg"] = "FAIL"
    finally:
        return json.dumps(response)


if __name__ == "__main__":

    import time

    server_log_path = "log/server/deamon"
    if not os.path.exists(server_log_path):
        os.makedirs(server_log_path)
    time_str = time.strftime('%Y-%m-%d_%H-%M-%S',time.localtime())
    logging.basicConfig(
        filename=server_log_path+"/"+time_str+".log",
        level="DEBUG",filemode="w")
    opts = parse_argument()
    server = Server(opts.config)

    WSGI_server = pywsgi.WSGIServer(('0.0.0.0',2680),app)
    logging.info("|deamon server start|")
    WSGI_server.serve_forever()
    logging.info("|deamon server stop|")
    

